<template>
  <div class="tree-list">
    <div class="tree-action">
      <el-button @click="onContextMenuClick('1')" type="primary">
        <el-icon><Plus /></el-icon>
        <span style="margin-left: 4px">新增站点</span>
      </el-button>
      <span class="total">总站数：{{ treeData.length }} 个</span>
    </div>
    <div class="tree-content">
      <el-tree
        v-if="treeData.length"
        default-expand-all
        :data="treeData"
        node-key="key"
        draggable
        :allow-drop="allowDrop"
        @node-drop="onDrop"
      >
        <template #default="{ data: { name, key } }">
          <div class="tree-node">
            <div class="tree-node-name">
              <StationIcon class="card-icon" :color="primary"></StationIcon>
              <span class="title">{{ name }}</span>
            </div>
            <div class="tree-node-btn">
              <el-button link type="primary" @click="swapDown(key)">
                <el-icon :size="16"><Bottom /></el-icon>
              </el-button>
              <el-button link type="primary" @click="onContextMenuClick('2', key, name)">
                <el-icon :size="16"><Edit /></el-icon>
              </el-button>
              <el-button link type="primary" @click="onContextMenuClick('3', key, name)">
                <el-icon :size="16"><Delete /></el-icon>
              </el-button>
            </div>
          </div>
        </template>
      </el-tree>
    </div>
    <!-- 弹窗组件 -->
    <el-dialog
      v-model="dialogVisible"
      :title="isEdit ? '编辑站点' : '创建站点'"
      :close-on-click-modal="false"
      destroy-on-close
      width="480"
    >
      <div class="modal-create-or-edit">
        <el-form ref="modalFormRef" :model="modalForm" :rules="modalFormRule" label-width="100">
          <el-form-item label="站点" prop="name">
            <el-input v-model="modalForm.name" placeholder="请输入站点名称" />
          </el-form-item>
        </el-form>
      </div>
      <div class="modal-create-or-edit-footer">
        <el-button @click="closeDialog()">取 消</el-button>
        <el-button type="primary" :loading="loadingSubmit" @click="submitForm(modalFormRef)">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts" name="stationTree">
import { ref, onMounted, watch, reactive } from "vue";
import { useGlobalStore } from "@/stores/modules/global";
import { storeToRefs } from "pinia";
import StationIcon from "../icon/station_icon.vue";
import { Route } from "@/api/interface/sysManagement";
import { ElMessage, FormInstance, FormRules, ElMessageBox } from "element-plus";

const globalStore = useGlobalStore();
const { primary } = storeToRefs(globalStore);

interface TreeNode {
  name: string;
  key: string | number;
  id?: number; // 可选属性
}

interface Props {
  data: Route.ResStationList[];
}

const props = withDefaults(defineProps<Props>(), {
  data: () => []
});

const emit = defineEmits(["treeChange"]);

watch(
  () => props.data,
  () => {
    initTreeData();
  }
);

const treeData = ref<TreeNode[]>([]);
const dialogVisible = ref(false);
const loadingSubmit = ref(false);
const isEdit = ref(false);
const modalFormRef = ref<FormInstance>();
let modalForm = reactive<TreeNode>({
  name: "",
  key: ""
});
const modalFormRule = reactive<FormRules>({
  name: [
    { required: true, message: "内容不能为空", trigger: "blur" },
    { min: 1, max: 64, message: "长度不超过64个字符", trigger: "blur" }
  ]
});

const onContextMenuClick = (menuKey, treeKey?, name?) => {
  Object.assign(modalForm, { key: treeKey, name: name });
  switch (menuKey) {
    case "1":
      // 新增
      isEdit.value = false;
      openDialog();
      break;
    case "2":
      // 编辑
      isEdit.value = true;
      openDialog();
      break;
    case "3":
      delDialog();
      // 删除
      break;
    default:
      break;
  }
};

const openDialog = () => {
  dialogVisible.value = true;
};

const closeDialog = () => {
  dialogVisible.value = false;
};

const submitForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.validate(async valid => {
    if (!valid) return;
    loadingSubmit.value = true;
    try {
      // 编辑
      if (isEdit.value) {
        treeData.value.forEach(item => {
          if (item.key === modalForm.key) {
            item.name = modalForm.name;
          }
        });
      } else {
        treeData.value.push({ ...modalForm });
      }
      getTreeData();
      closeDialog();
      loadingSubmit.value = false;
    } finally {
      loadingSubmit.value = false;
    }
  });
};

const delDialog = () => {
  ElMessageBox.confirm(`是否确定删除站点：${modalForm.name}`, "删除确认", {
    confirmButtonText: "确 定",
    cancelButtonText: "取 消",
    type: "warning"
  }).then(() => {
    treeData.value = treeData.value.filter(a => a.key !== modalForm.key);
    getTreeData();
  });
};

const initTreeData = () => {
  treeData.value = [];
  props.data.forEach(item => {
    const list: TreeNode = {
      name: item.name,
      key: guid(),
      id: item.id || undefined
    };
    treeData.value.push(list);
  });
};
// 生成随机key
const guid = () => {
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
    const r = (Math.random() * 16) | 0;
    const v = c === "x" ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
};

const getTreeData = () => {
  emit("treeChange", treeData.value);
};

const allowDrop = (draggingNode, dropNode, type) => {
  // 确保不是放置在节点内部
  if (type !== "inner") {
    // 可以放置在兄弟节点之前或之后
    return true;
  }
  return false;
};

const onDrop = () => {
  getTreeData();
};

/**
 * 与下面的交换位置
 */
const swapDown = key => {
  const data = [...treeData.value];
  const list: TreeNode | undefined = data.find(a => a.key === key);
  if (!list) return;
  const index = data.indexOf(list);
  // 不是最后一个则交换位置
  if (index !== data.length - 1) {
    data.splice(index, 1, ...data.splice(index + 1, 1, data[index]));
    treeData.value = data;
    getTreeData();
  } else {
    ElMessage({
      message: "已是最后一个站点，无法交换顺序",
      type: "warning"
    });
  }
};

onMounted(() => {
  initTreeData();
});
</script>

<style lang="scss" scoped>
.tree-list {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  .tree-action {
    padding: 16px 0;
    border-top: 1px dashed rgb(0 0 0 / 20%);
    .total {
      float: right;
      line-height: 32px;
    }
  }
  .tree-content {
    flex: 1;
    padding: 14px 0;
    overflow-y: auto;
    text-align: left;
    background: rgb(255 255 255 / 100%);
    border: 1px solid rgb(229 229 229 / 100%);
    border-radius: 8px;
    .tree-node {
      width: 100%;
      .tree-node-name {
        display: inline-flex;
        gap: 8px;
        align-items: center;
      }
      .tree-node-btn {
        float: right;
      }
    }
  }
}
.card-icon {
  width: 22px;
  height: 22px;
}
:deep() .el-tree-node__content {
  padding: 9px 24px;
}
:deep() .el-tree-node:focus > .el-tree-node__content {
  background: rgb(31 140 242 / 10%);
}
::-webkit-scrollbar {
  width: 3px;
  height: 3px;
}
::-webkit-scrollbar-thumb {
  background-color: #99a9bf;
  border-radius: 5px;
  box-shadow: inset 0 0 5px rgb(0 0 0 / 20%);
}
::-webkit-scrollbar-track {
  background-color: #d3dce6;
  border-radius: 5px;
  box-shadow: inset 0 0 5px rgb(0 0 0 / 20%);
}
.modal-create-or-edit-footer {
  text-align: right;
}
</style>
